package com.summer.filesync.api;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.summer.filesync.config.ConfigManager;
import com.summer.filesync.config.SystemConfig;
import com.summer.filesync.network.NetworkManager;
import com.summer.filesync.security.AuthenticationResult;
import com.summer.filesync.security.SecurityHandler;
import com.summer.filesync.security.UserRole;
import com.summer.filesync.sync.FileWatcher;
import com.summer.filesync.util.Logger;
import java.io.*;
import java.net.*;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/** HTTP API服务器 为TUI界面提供REST API接口 */
public class ApiServer {
  private static final Logger logger = Logger.getLogger(ApiServer.class);
  private static final int DEFAULT_API_PORT = 8889;

  private ServerSocket serverSocket;
  private ExecutorService executor;
  private boolean isRunning = false;
  private int apiPort;
  private ObjectMapper jsonMapper;
  private SecurityHandler securityHandler;

  // 系统组件引用
  private NetworkManager networkManager;
  private FileWatcher fileWatcher;

  public ApiServer() {
    ConfigManager config = ConfigManager.getInstance();
    this.apiPort = config.getIntProperty("api.port", DEFAULT_API_PORT);
    this.jsonMapper = new ObjectMapper();
    this.executor = Executors.newFixedThreadPool(5);
    this.securityHandler = new SecurityHandler();
  }

  /** 启动API服务器 */
  public void start() throws IOException {
    if (isRunning) {
      logger.warn("API Server is already running");
      return;
    }

    this.networkManager = NetworkManager.getInstance();

    serverSocket = new ServerSocket(apiPort);
    isRunning = true;

    // 启动服务器监听线程
    executor.submit(
        () -> {
          logger.info("API Server started on port " + apiPort);

          while (isRunning && !serverSocket.isClosed()) {
            try {
              Socket clientSocket = serverSocket.accept();
              executor.submit(() -> handleRequest(clientSocket));
            } catch (IOException e) {
              if (isRunning) {
                logger.error("Error accepting API connection", e);
              }
            }
          }
        });

    logger.info("API Server listening on port " + apiPort);
  }

  /** 停止API服务器 */
  public void stop() {
    isRunning = false;

    try {
      if (serverSocket != null && !serverSocket.isClosed()) {
        serverSocket.close();
      }
    } catch (IOException e) {
      logger.error("Error closing API server socket", e);
    }

    if (executor != null) {
      executor.shutdown();
    }

    logger.info("API Server stopped");
  }

  /** 处理HTTP请求 */
  private void handleRequest(Socket clientSocket) {
    try (BufferedReader reader =
            new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
        PrintWriter writer = new PrintWriter(clientSocket.getOutputStream(), true)) {

      // 读取HTTP请求行
      String requestLine = reader.readLine();
      if (requestLine == null) return;

      String[] parts = requestLine.split(" ");
      if (parts.length < 2) return;

      String method = parts[0];
      String path = parts[1];

      // 读取请求头
      Map<String, String> headers = new HashMap<>();
      String line;
      while ((line = reader.readLine()) != null && !line.isEmpty()) {
        int colonIndex = line.indexOf(':');
        if (colonIndex > 0) {
          String headerName = line.substring(0, colonIndex).trim().toLowerCase();
          String headerValue = line.substring(colonIndex + 1).trim();
          headers.put(headerName, headerValue);
        }
      }

      // 读取请求体（如果有）
      String requestBody = "";
      String contentLengthStr = headers.get("content-length");
      if (contentLengthStr != null) {
        try {
          int contentLength = Integer.parseInt(contentLengthStr);
          if (contentLength > 0) {
            char[] buffer = new char[contentLength];
            int totalRead = 0;
            while (totalRead < contentLength) {
              int read = reader.read(buffer, totalRead, contentLength - totalRead);
              if (read == -1) break;
              totalRead += read;
            }
            requestBody = new String(buffer, 0, totalRead);
          }
        } catch (NumberFormatException e) {
          logger.warn("Invalid Content-Length header: " + contentLengthStr);
        }
      }

      // 处理CORS预检请求
      if ("OPTIONS".equals(method)) {
        sendCorsResponse(writer);
        return;
      }

      // 处理API路径
      String response = handleApiRequest(method, path, headers, requestBody);

      // 发送HTTP响应
      writer.println("HTTP/1.1 200 OK");
      writer.println("Content-Type: application/json; charset=utf-8");
      writer.println("Access-Control-Allow-Origin: *");
      writer.println("Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS");
      writer.println("Access-Control-Allow-Headers: Content-Type, Authorization");
      writer.println("Connection: close");
      writer.println();
      writer.println(response);

    } catch (Exception e) {
      logger.error("Error handling API request", e);
    } finally {
      try {
        clientSocket.close();
      } catch (IOException e) {
        logger.error("Error closing client socket", e);
      }
    }
  }

  /** 发送CORS预检响应 */
  private void sendCorsResponse(PrintWriter writer) {
    writer.println("HTTP/1.1 200 OK");
    writer.println("Access-Control-Allow-Origin: *");
    writer.println("Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS");
    writer.println("Access-Control-Allow-Headers: Content-Type, Authorization");
    writer.println("Connection: close");
    writer.println();
  }

  /** 处理API请求并返回JSON响应 */
  private String handleApiRequest(
      String method, String path, Map<String, String> headers, String requestBody) {
    try {
      // 获取认证信息
      String authHeader = headers.get("authorization");
      String authToken = SecurityHandler.parseAuthToken(authHeader);

      // 处理公开的认证端点
      if ("POST".equals(method) && "/api/login".equals(path)) {
        return securityHandler.handleLogin(requestBody);
      }

      if ("POST".equals(method) && "/api/logout".equals(path)) {
        return securityHandler.handleLogout(authToken);
      }

      // 处理安全状态查询（低权限）
      if ("GET".equals(method) && "/api/security".equals(path)) {
        AuthenticationResult authResult =
            securityHandler.validateRequest(authToken, UserRole.Permissions.VIEW_STATUS);
        if (!authResult.isSuccess()) {
          return createErrorResponse("认证失败: " + authResult.getErrorMessage());
        }
        return securityHandler.getSecurityStatus();
      }

      // 处理用户管理端点（需要管理员权限）
      if ("POST".equals(method) && "/api/users".equals(path)) {
        return securityHandler.createUser(requestBody, authToken);
      }

      if ("POST".equals(method) && "/api/apikeys".equals(path)) {
        return securityHandler.createApiKey(requestBody, authToken);
      }

      // 处理现有的API端点，增加权限检查
      switch (path) {
        case "/api/status":
          return handleSecureEndpoint(
              authToken, UserRole.Permissions.VIEW_STATUS, this::getSystemStatus);
        case "/api/config":
          if ("GET".equals(method)) {
            return handleSecureEndpoint(
                authToken, UserRole.Permissions.VIEW_CONFIG, this::getSystemConfig);
          } else if ("POST".equals(method) || "PUT".equals(method)) {
            return handleSecureEndpoint(
                authToken,
                UserRole.Permissions.MODIFY_CONFIG,
                () -> updateSystemConfig(requestBody));
          }
          break;
        case "/api/network":
          return handleSecureEndpoint(
              authToken, UserRole.Permissions.VIEW_STATUS, this::getNetworkStatus);
        case "/api/files":
          return handleSecureEndpoint(
              authToken, UserRole.Permissions.VIEW_STATUS, this::getFileStatus);
        case "/api/logs":
          return handleSecureEndpoint(
              authToken, UserRole.Permissions.VIEW_STATUS, this::getRecentLogs);
        default:
          return createErrorResponse("Unknown API endpoint: " + path);
      }

      return createErrorResponse("Unsupported method for endpoint: " + method + " " + path);
    } catch (Exception e) {
      logger.error("Error processing API request: " + path, e);
      return createErrorResponse("Internal server error: " + e.getMessage());
    }
  }

  /** 处理需要认证的端点 */
  private String handleSecureEndpoint(
      String authToken, int requiredPermission, ApiHandler handler) {
    AuthenticationResult authResult =
        securityHandler.validateRequest(authToken, requiredPermission);
    if (!authResult.isSuccess()) {
      return createErrorResponse("认证失败: " + authResult.getErrorMessage());
    }

    try {
      return handler.handle();
    } catch (Exception e) {
      logger.error("Error in secure endpoint handler", e);
      return createErrorResponse("处理请求时发生错误: " + e.getMessage());
    }
  }

  /** API处理器接口 */
  @FunctionalInterface
  private interface ApiHandler {
    String handle() throws Exception;
  }

  /** 获取系统状态 */
  private String getSystemStatus() {
    try {
      ObjectNode status = jsonMapper.createObjectNode();
      ConfigManager config = ConfigManager.getInstance();

      // 基本信息
      status.put("nodeId", config.getProperty(SystemConfig.NODE_ID, "unknown"));
      status.put("nodeName", config.getProperty(SystemConfig.NODE_NAME, "SyncNode"));
      status.put("version", config.getProperty(SystemConfig.NODE_VERSION, "1.0.0"));
      status.put("uptime", System.currentTimeMillis() - startTime);
      status.put("timestamp", System.currentTimeMillis());

      // 服务状态
      ObjectNode services = status.putObject("services");
      services.put("network", networkManager != null && networkManager.isRunning());
      services.put("fileWatcher", fileWatcher != null && fileWatcher.isRunning());
      services.put("api", isRunning);

      // 网络信息
      ObjectNode network = status.putObject("network");
      network.put("port", config.getIntProperty(SystemConfig.NETWORK_PORT, 8888));
      network.put("apiPort", apiPort);
      if (networkManager != null) {
        network.put("connections", networkManager.getConnectedNodeIds().size());
        network.put("maxConnections", config.getIntProperty(SystemConfig.MAX_CONNECTIONS, 10));
      }

      return jsonMapper.writeValueAsString(status);
    } catch (Exception e) {
      logger.error("Error getting system status", e);
      return createErrorResponse("Failed to get system status");
    }
  }

  /** 获取系统配置 */
  private String getSystemConfig() {
    try {
      ObjectNode config = jsonMapper.createObjectNode();
      ConfigManager configManager = ConfigManager.getInstance();

      // 网络配置
      ObjectNode network = config.putObject("network");
      network.put("port", configManager.getIntProperty(SystemConfig.NETWORK_PORT, 8888));
      network.put("maxConnections", configManager.getIntProperty(SystemConfig.MAX_CONNECTIONS, 10));
      network.put("timeout", configManager.getIntProperty(SystemConfig.NETWORK_TIMEOUT, 30000));
      network.put(
          "heartbeatInterval",
          configManager.getLongProperty(SystemConfig.HEARTBEAT_INTERVAL, 30000));

      // 同步配置
      ObjectNode sync = config.putObject("sync");
      sync.put(
          "autoEnabled", configManager.getBooleanProperty(SystemConfig.AUTO_SYNC_ENABLED, true));
      sync.put("interval", configManager.getLongProperty(SystemConfig.SYNC_INTERVAL, 60000));
      sync.put(
          "conflictStrategy",
          configManager.getProperty(SystemConfig.CONFLICT_STRATEGY, "TIMESTAMP_PRIORITY"));
      sync.put(
          "watchDirectories", configManager.getProperty(SystemConfig.WATCH_DIRECTORIES, "sync"));

      // 日志配置
      ObjectNode log = config.putObject("log");
      log.put("level", configManager.getProperty(SystemConfig.LOG_LEVEL, "INFO"));
      log.put("fileEnabled", configManager.getBooleanProperty(SystemConfig.LOG_FILE_ENABLED, true));
      log.put("filePath", configManager.getProperty(SystemConfig.LOG_FILE_PATH, "logs/system.log"));

      return jsonMapper.writeValueAsString(config);
    } catch (Exception e) {
      logger.error("Error getting system config", e);
      return createErrorResponse("Failed to get system config");
    }
  }

  /** 获取网络状态 */
  private String getNetworkStatus() {
    try {
      ObjectNode network = jsonMapper.createObjectNode();

      if (networkManager != null) {
        network.put("isRunning", networkManager.isRunning());

        // 连接的节点
        ArrayNode nodes = network.putArray("connectedNodes");
        for (String nodeId : networkManager.getConnectedNodeIds()) {
          ObjectNode node = nodes.addObject();
          node.put("nodeId", nodeId);
          node.put("status", "connected");
          // TODO: 添加更多节点信息
        }

        // 消息队列状态
        ObjectNode queues = network.putObject("messageQueues");
        queues.put("incoming", networkManager.getIncomingMessageQueue().size());
        queues.put("outgoing", networkManager.getOutgoingMessageQueue().size());
      } else {
        network.put("isRunning", false);
        network.putArray("connectedNodes");
      }

      return jsonMapper.writeValueAsString(network);
    } catch (Exception e) {
      logger.error("Error getting network status", e);
      return createErrorResponse("Failed to get network status");
    }
  }

  /** 获取文件状态 */
  private String getFileStatus() {
    try {
      ObjectNode files = jsonMapper.createObjectNode();

      if (fileWatcher != null) {
        files.put("isRunning", fileWatcher.isRunning());
        files.put("eventQueueSize", fileWatcher.getEventQueueSize());

        // 监控的目录
        ArrayNode paths = files.putArray("monitoredPaths");
        for (String path : fileWatcher.getMonitoredPaths()) {
          paths.add(path);
        }

        // TODO: 添加最近的文件事件
        files.putArray("recentEvents");
      } else {
        files.put("isRunning", false);
        files.put("eventQueueSize", 0);
        files.putArray("monitoredPaths");
        files.putArray("recentEvents");
      }

      return jsonMapper.writeValueAsString(files);
    } catch (Exception e) {
      logger.error("Error getting file status", e);
      return createErrorResponse("Failed to get file status");
    }
  }

  /** 获取最近日志 */
  private String getRecentLogs() {
    try {
      ObjectNode logs = jsonMapper.createObjectNode();
      ArrayNode entries = logs.putArray("entries");

      // TODO: 实现日志读取逻辑
      // 暂时返回示例日志
      ObjectNode entry = entries.addObject();
      entry.put("timestamp", System.currentTimeMillis());
      entry.put("level", "INFO");
      entry.put("message", "System running normally");

      logs.put("timestamp", System.currentTimeMillis());
      return jsonMapper.writeValueAsString(logs);
    } catch (Exception e) {
      logger.error("Error getting recent logs", e);
      return createErrorResponse("Failed to get recent logs");
    }
  }

  /** 更新系统配置 */
  private String updateSystemConfig(String requestBody) {
    try {
      @SuppressWarnings("unchecked")
      Map<String, Object> configData = jsonMapper.readValue(requestBody, Map.class);

      ConfigManager configManager = ConfigManager.getInstance();

      // 更新网络配置
      if (configData.containsKey("network")) {
        @SuppressWarnings("unchecked")
        Map<String, Object> network = (Map<String, Object>) configData.get("network");
        updateNetworkConfig(configManager, network);
      }

      // 更新同步配置
      if (configData.containsKey("sync")) {
        @SuppressWarnings("unchecked")
        Map<String, Object> sync = (Map<String, Object>) configData.get("sync");
        updateSyncConfig(configManager, sync);
      }

      // 更新日志配置
      if (configData.containsKey("log")) {
        @SuppressWarnings("unchecked")
        Map<String, Object> log = (Map<String, Object>) configData.get("log");
        updateLogConfig(configManager, log);
      }

      // 保存配置
      configManager.saveConfig();

      ObjectNode response = jsonMapper.createObjectNode();
      response.put("success", true);
      response.put("message", "配置更新成功");
      response.put("timestamp", System.currentTimeMillis());

      logger.info("系统配置已更新");
      return jsonMapper.writeValueAsString(response);

    } catch (Exception e) {
      logger.error("Error updating system config", e);
      return createErrorResponse("Failed to update system config: " + e.getMessage());
    }
  }

  /** 更新网络配置 */
  private void updateNetworkConfig(ConfigManager configManager, Map<String, Object> network) {
    if (network.containsKey("port")) {
      configManager.setProperty(SystemConfig.NETWORK_PORT, network.get("port").toString());
    }
    if (network.containsKey("maxConnections")) {
      configManager.setProperty(
          SystemConfig.MAX_CONNECTIONS, network.get("maxConnections").toString());
    }
    if (network.containsKey("timeout")) {
      configManager.setProperty(SystemConfig.NETWORK_TIMEOUT, network.get("timeout").toString());
    }
    if (network.containsKey("heartbeatInterval")) {
      configManager.setProperty(
          SystemConfig.HEARTBEAT_INTERVAL, network.get("heartbeatInterval").toString());
    }
  }

  /** 更新同步配置 */
  private void updateSyncConfig(ConfigManager configManager, Map<String, Object> sync) {
    if (sync.containsKey("autoEnabled")) {
      configManager.setProperty(SystemConfig.AUTO_SYNC_ENABLED, sync.get("autoEnabled").toString());
    }
    if (sync.containsKey("interval")) {
      configManager.setProperty(SystemConfig.SYNC_INTERVAL, sync.get("interval").toString());
    }
    if (sync.containsKey("conflictStrategy")) {
      configManager.setProperty(
          SystemConfig.CONFLICT_STRATEGY, sync.get("conflictStrategy").toString());
    }
    if (sync.containsKey("watchDirectories")) {
      configManager.setProperty(
          SystemConfig.WATCH_DIRECTORIES, sync.get("watchDirectories").toString());
    }
  }

  /** 更新日志配置 */
  private void updateLogConfig(ConfigManager configManager, Map<String, Object> log) {
    if (log.containsKey("level")) {
      configManager.setProperty(SystemConfig.LOG_LEVEL, log.get("level").toString());
    }
    if (log.containsKey("fileEnabled")) {
      configManager.setProperty(SystemConfig.LOG_FILE_ENABLED, log.get("fileEnabled").toString());
    }
    if (log.containsKey("filePath")) {
      configManager.setProperty(SystemConfig.LOG_FILE_PATH, log.get("filePath").toString());
    }
  }

  /** 创建错误响应 */
  private String createErrorResponse(String message) {
    try {
      ObjectNode error = jsonMapper.createObjectNode();
      error.put("error", true);
      error.put("message", message);
      error.put("timestamp", System.currentTimeMillis());
      return jsonMapper.writeValueAsString(error);
    } catch (Exception e) {
      return "{\"error\":true,\"message\":\"JSON serialization failed\"}";
    }
  }

  /** 设置文件监控器引用 */
  public void setFileWatcher(FileWatcher fileWatcher) {
    this.fileWatcher = fileWatcher;
  }

  // 系统启动时间
  private static final long startTime = System.currentTimeMillis();

  public boolean isRunning() {
    return isRunning;
  }

  public int getApiPort() {
    return apiPort;
  }
}
